#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <time.h>

#define RX8900_I2C_ADDR 0x32
#define DEV_I2C_NAME ("/dev/i2c-1")

static int i2c_fd = -1;

// 初始化I2C通信
int rtc_init() {
    i2c_fd = open(DEV_I2C_NAME, O_RDWR);
    if (i2c_fd < 0) {
        perror("Failed to open I2C device");
        return -1;
    }

    if (ioctl(i2c_fd, I2C_SLAVE, RX8900_I2C_ADDR) < 0) {
        perror("Failed to set I2C slave address");
        close(i2c_fd);
        return -1;
    }

    return 0;
}

// 从RTC读取时间
int rtc_read_time(struct tm *time) {
    unsigned char buf[7];
    unsigned char start_reg = 0x00; // 起始寄存器地址

    if (write(i2c_fd, &start_reg, 1) != 1) {
        perror("Failed to set register address for reading");
        return -1;
    }

    if (read(i2c_fd, buf, 7) != 7) {
        perror("Failed to read time data");
        return -1;
    }

  
    time->tm_sec = (buf[0] & 0x0F) + ((buf[0] >> 4) & 0x07) * 10;
    time->tm_min = (buf[1] & 0x0F) + ((buf[1] >> 4) & 0x07) * 10;
    time->tm_hour = (buf[2] & 0x0F) + ((buf[2] >> 4) & 0x03) * 10; // 假设24小时制
    time->tm_wday = buf[3] & 0x07; // 直接读取 (0=Sun)
    time->tm_mday = (buf[4] & 0x0F) + ((buf[4] >> 4) & 0x03) * 10;
    time->tm_mon = ((buf[5] & 0x0F) + ((buf[5] >> 4) & 0x01) * 10) - 1; // BCD 1-12 -> tm_mon 0-11
    time->tm_year = (buf[6] & 0x0F) + ((buf[6] >> 4) & 0x0F) * 10 + 100; // BCD 00-99 -> tm_year 100+ (since 1900)

    printf("Read time (Dec):\n");
    printf("  tm_year: %d (from BCD 0x%02X)\n", time->tm_year + 1900, buf[6]);
    printf("  tm_mon : %d (from BCD 0x%02X)\n", time->tm_mon + 1, buf[5]);
    printf("  tm_mday: %d (from BCD 0x%02X)\n", time->tm_mday, buf[4]);
    printf("  tm_hour: %d (from BCD 0x%02X)\n", time->tm_hour, buf[2]);
    printf("  tm_min : %d (from BCD 0x%02X)\n", time->tm_min, buf[1]);
    printf("  tm_sec : %d (from BCD 0x%02X)\n", time->tm_sec, buf[0]);
    printf("  tm_wday: %d (from 0x%02X)\n", time->tm_wday, buf[3]);

    return 0;
}

// 设置RTC时间
int rtc_set_time(struct tm *time) {
   
    unsigned char year_bcd = time->tm_year % 100; // tm_mon 是 0-11, RTC 需要 1-12
    unsigned char month_bcd = time->tm_mon + 1;
    if (year_bcd > 100 || time->tm_mon > 11 || time->tm_mday > 31 ||
        time->tm_hour > 23 || time->tm_min > 59 || time->tm_sec > 59 || time->tm_wday > 6) {
        printf("输入时间参数无效!\n");
        return -1;
    }

    unsigned char buf[8];
    buf[0] = 0x00; // 起始寄存器地址

    buf[1] = ((time->tm_sec / 10) << 4) | (time->tm_sec % 10);      // 秒   -> Reg 0x00
    buf[2] = ((time->tm_min / 10) << 4) | (time->tm_min % 10);      // 分   -> Reg 0x01
    buf[3] = ((time->tm_hour / 10) << 4) | (time->tm_hour % 10);    // 时   -> Reg 0x02
    buf[4] = time->tm_wday;                                         // 星期 -> Reg 0x03 (RX8900 直接用二进制)
    buf[5] = ((time->tm_mday / 10) << 4) | (time->tm_mday % 10);    // 日   -> Reg 0x04
    buf[6] = ((time->tm_mon / 10) << 4) | ((time->tm_mon + 1 )% 10);            // 月   -> Reg 0x05
    buf[7] = ((year_bcd / 10) << 4) | (year_bcd % 10);    // 年   -> Reg 0x06

    if (write(i2c_fd, buf, 8) != 8) { // 写入8个字节: 地址 + 7个数据字节 (Reg 0x00-0x06)
        perror("Failed to set time");
        return -1;
    }

    return 0;
}

// 关闭RTC设备
void rtc_close() {
    if (i2c_fd >= 0) {
        close(i2c_fd);
        i2c_fd = -1;
    }
}

int rtc_sync_to_system() {
    struct tm rtc_time;
    char cmd[100];
    
    if (rtc_read_time(&rtc_time) < 0) {
        return -1;
    }
    
    // 构建date命令字符串
    snprintf(cmd, sizeof(cmd), "date -s \"%04d-%02d-%02d %02d:%02d:%02d\"", 
             rtc_time.tm_year + 1900, rtc_time.tm_mon + 1, rtc_time.tm_mday,
             rtc_time.tm_hour, rtc_time.tm_min, rtc_time.tm_sec);
    
    return system(cmd);
}

int system_sync_to_rtc() {
    struct tm sys_time;
    time_t t = time(NULL);
    
    if (t == (time_t)-1) {
        perror("Failed to get system time");
        return -1;
    }
    
    localtime_r(&t, &sys_time);
    return rtc_set_time(&sys_time);
}
